/**************************************************************************** The following code was taken from the Network Developer's Resource, published by RoseWare. All contents are Copyright (c) 1993, RoseWare. All Rights Reserved. This material is made available as a service for subscribers of the Network Developer's Resource. This material is not public domain. Simply put, if you are not a subscriber of the Network Developer's Resource, you are using this material illegally. Those interested in subscribing should contact RoseWare via: CompuServe: 76711,110 Internet: 76711.110@compuserve.com Phone: (704) 258-9166 Fax: (704) 258-9374 BBS: (704) 258-8675 US Mail: P.O. Box 8564 Asheville, NC 28814-8564 Also see the file SUBSCRIB.TXT in this ZIP file... ****************************************************************************/ Developing NetWare Utilities Fast The Visual Basic installed base has grown tremendously since its introduction as a programming tool. It has quickly become the development platform of choice for a wide range of applications. Writing network utilities and network aware applications using Visual Basic for Windows is a natural. With just a little help from your favorite C compiler, the power of NetWare could easily be at your fingertips. There have been a number of articles on calling Novells own DLLs from Visual Basic but, if you want to get maximum control, flexibility and support for networks other than NetWare, you have two options: Write your own DLLs. Buy an add-on network package with support for multiple networks, source code, documentation and demonstration programs. If you are going to write your own DLLs, you must first decide on a C compiler. I like the Microsoft Visual C/C++ one. It is a high quality tool and comes with an excellent debugger, CodeView for Windows. Also, documentation on interfacing DLLs with this compiler are available from Microsoft on CompuServe. Once youve decided on the tools, you are ready to write some code. My recommendation is to start simple. Writing high quality DLLs can get real complicated in the blink of an eye. I have prepared a demonstration program for this article which is simple and useful. It is a program to check the security equivalences of a Bindery Object. Microsoft Visual C/C++ .DEF code: LIBRARY SECEQUIV EXETYPE WINDOWS DESCRIPTION 'Security Equivalence Demo' CODE PRELOAD MOVEABLE DISCARDABLE DATA PRELOAD MOVEABLE SINGLE HEAPSIZE 8192 EXPORTS WEP PRIVATE Microsoft Visual C/C++ C DLL code: // some includes #include #include #include #include #include #include #include #include #include #include #include #include // Read property value request structure struct readPropertyValueRequest { WORD length; BYTE req_no; WORD object_type; BYTE object_name_length; BYTE object_name[48]; BYTE segment_number; BYTE property_name_length; BYTE property_name[16]; }; // Read property value reply structure struct readPropertyValueReply { WORD length; BYTE property_value[128]; BYTE more_segments; BYTE property_flags; }; // return structure for Visual Basic // we just want to return the Bindery Object IDs // found in the 128 Byte property_value element typedef struct { LONG object_ID[31]; } gSecEquiv; // Returns: completion code, array of Bindery Object IDs // Accepts: Bindery Object Name int FAR PASCAL _export NW_SecurityEquivalence(char far *cName, struct gSecEquiv *SEquiv) { struct readPropertyValueRequest request; struct readPropertyValueReply reply; int i=0,ccode; HINSTANCE hNetWareDrv; LONG object=0, objectID[31]; long (FAR PASCAL *NetWareRequest) (void); NetWareRequest = NULL; // See if the NETWARE.DRV module is loaded // and attempt to obtain a handle. hNetWareDrv = GetModuleHandle("NETWARE"); // If there is a handle, perform the function. if(hNetWareDrv > HINSTANCE_ERROR) { // Initialize the request and reply structures. _fmemset(&request, 0x00, sizeof(request)); _fmemset(&reply, 0x00, sizeof(reply)); // Put the Bindery Object Name into the request structure. _fstrcpy(request.object_name, cName); // Obtain the Bindery Object Names length. request.object_name_length=sizeof(request.object_name); // Its a Bindery Object of type User. request.object_type=0x0100; // The first call needs a segment number of 1. request.segment_number=1; // The property name is SECURITY_EQUALS _fstrcpy(request.property_name, "SECURITY_EQUALS"); // Obtain the size of the property name. request.property_name_length=sizeof(request.property_name); // Get the size of the request structure. request.length=sizeof(request)-2; // The function number for this NetWare API is 0x3D request.req_no=0x3D; // Get the size of the return structure. reply.length=sizeof(reply)-2; // Make the actual function call and // write some code of your own to evaluate // the return code. ccode = NetWareCall(0xE3, (LPSTR)&request, (LPSTR)&reply); // Go through the 128 Byte reply.property_value element // looking for Bindery Object IDs. for (i=0; i<32; i++) { // Each Bindery Object ID is 4 bytes. object = *((LONG *)(reply.property_value + (I*4))); // Get the data into a temporary array of LONGs. objectID[i] = object; object = 0; } // Move the data into our Visual Basic return structure. _fmemmove(SEquiv, &objectID, sizeof(gSecEquiv)); return ccode; } else { // the NETWARE.DRV DLL is not loaded // call the error function. NetWareDriverError(); } }; // This function does the actual call to the NetWare shell. WORD NetWareCall(BYTE function, LPSTR request, LPSTR reply) { // Some of this code could be found in previous issues of NDR // You may want to consult those back issues for some // understanding of this function if it is not obvious. BYTE ccode; HINSTANCE hNetWareDrv; long (FAR PASCAL *NetWareRequest) (void); long (FAR PASCAL *NetWareRequest2) (void); NetWareRequest = NULL; hNetWareDrv = GetModuleHandle("NETWARE"); (FARPROC) NetWareRequest = GetProcAddress(hNetWareDrv, "NetWareRequest"); NetWareRequest2 = NetWareRequest; _asm xor al,al _asm push ds _asm push es _asm mov ah,function _asm lds si,request _asm les di,reply NetWareRequest2(); _asm pop es _asm pop ds _asm xor ah,ah _asm mov ccode,al return (WORD)ccode; }; // If the module was not loaded, this function gets called. void NetWareDriverError(void) { // Change this to an error message of your choice. // You could remove the message box code and return a number MessageBox(NULL,"NETWARE.DRV not loaded. Check Windows Setup and/or NetWare Shell", "FATAL ERROR",MB_ICONSTOP | MB_OK); }; Microsoft Visual Basic for Windows 3.0 code: // Dimension an array of Longs to receive the return from your DLL. Type ObjectIDs object_ID(31) As Long End Type // This is the function declaration. Declare Function NW_SecurityEquivalence% Lib "SECEQUIV.DLL" (ByVal _ Name$, IDs As ObjectIDs) // Dimension an array of type ObjectIDs Dim NWIDs As ObjectIDs // Call the function passing a Bindery Object Name ccode% = NW_SecurityEquivalence("GUEST", NWIDs) // Look at the first Bindery Object ID returned // and evaluate it. If it is a 0 then there are // no Bindery Object IDs or this is the last one. Label1.Caption = Hex$(NW_SwapLong(NWIDs.object_ID(0))) You can enhance this program by using the supervisor Bindery Object ID and comparing it to the returned values to check for supervisor equivalence. Also, in the basic program you could return the non-zero values to a list box for selection and use into another function. Remember that the values returned are in Hi-Lo format. Using Visual Basic for Windows 3.0 with C may just give you the best of all worlds. Stephen Casella is the author of NetPak Professional, a multi-network add-on library for Visual Basic for Windows and Visual Basic for MS-DOS. NetPak Professional supports, NetWare 2.X, 3.X, 4.X and Windows for Workgroups and is sold by Crescent Software, Inc. in Ridgefield, Connecticut. It can be ordered by calling (203-438-5300).